<?php

declare(strict_types=1);

namespace App\Common;

use Lcobucci\JWT\Signer\Hmac;
use Qbhy\SimpleJwt\Interfaces\Encrypter;

class HmacHS256Encrypter extends Hmac implements Encrypter
{
    private $secret = '';

    public function __construct($secret)
    {
        $this->secret = $secret;
    }

    public function signature(string $payload): string
    {
        return hash_hmac($this->getAlgorithm(), $payload, $this->secret, true);
    }

    public function check(string $payload, string $expected): bool
    {
        $callback = function_exists('hash_equals') ? 'hash_equals' : [$this, 'hashEquals'];

        return call_user_func($callback, $expected, $this->signature($payload));
    }

    /**
     * PHP < 5.6 timing attack safe hash comparison
     *
     * @internal
     *
     * @param string $expected
     * @param string $generated
     *
     * @return boolean
     */
    public function hashEquals($expected, $generated)
    {
        $expectedLength = strlen($expected);

        if ($expectedLength !== strlen($generated)) {
            return false;
        }

        $res = 0;

        for ($i = 0; $i < $expectedLength; ++$i) {
            $res |= ord($expected[$i]) ^ ord($generated[$i]);
        }

        return $res === 0;
    }

    public static function alg(): string
    {
        return 'HS256';
    }

    /**
     * {@inheritdoc}
     */
    public function getAlgorithmId()
    {
        return 'HS256';
    }

    /**
     * {@inheritdoc}
     */
    public function getAlgorithm()
    {
        return 'sha256';
    }

}
